package org.fizz.ass.html;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import org.fizz.ass.AssConstants;

/**
 * HTML元素类
 * @author FIZZ
 * @version ass-1.0, 2014-4-23
 * @since 1.0
 */
public class Element implements AssConstants {

	/**
	 * 元素名
	 */
	private String name;
	
	/**
	 * 元素的Text
	 */
	private String text;
	
	/**
	 * 属性集合
	 */
	private Map<String, String> attributes;
	
	/**
	 * 子元素
	 */
	private Vector<Element> childElements;
	
	/**
	 * 父元素
	 */
	private Element parentElement;
	
	/**
	 * 构造一个元素
	 * @param name 元素名称
	 * @param text 元素的Text
	 * @since 1.0
	 */
	public Element(String name){
		this.name = name;
		
		attributes = new HashMap<String, String>();
		childElements = new Vector<Element>();
	}

	/**
	 * 返回元素的名称
	 * @return 元素的名称
	 * @since 1.0
	 */
	public String getName() {
		return name;
	}

	/**
	 * 设置Text
	 * @param text
	 * @since 1.0
	 */
	public void setText(String text) {
		this.text = text;
	}

	/**
	 * 返回元素的Text
	 * @return 元素的Text
	 * @since 1.0
	 */
	public String getText() {
		if(text != null && text.trim() != ""){
			return text;
		}
		return "";
	}

	/**
	 * 返回HTML元素的属性集合
	 * @return 如果HTML元素的属性集合中有属性，返回属性集合，否则返回<tt>null<tt>
	 * @since 1.0
	 */
	public Map<String, String> getAttributes() {
		if(attributes != null && attributes.size() > 0){
			return attributes;
		}
		return null;
	}

	/**
	 * 返回HTML元素的子元素集合
	 * @return 如果HTML元素的子元素集合中有元素，返回子元素集合，否则返回<tt>null<tt>
	 * @since 1.0
	 */
	public Vector<Element> getChildElements() {
		if(childElements != null && childElements.size() > 0){
			return childElements;
		}
		return null;
	}
	
	/**
	 * 添加一个子元素
	 * @param childElement 子元素
	 * @since 1.0
	 */
	public void addChildElement(Element childElement){
		childElements.add(childElement);
	}
	
	/**
	 * 根据索引返回子元素
	 * @param index 索引位置
	 * @since 1.0
	 */
	public Element getChildElementAt(int index){
		return childElements.elementAt(index);
	}
	
	/**
	 * 返回第一个子元素
	 * @since 1.0
	 */
	public Element getFirstElement(){
		return childElements.firstElement();
	}
	
	/**
	 * 返回最后一个子元素
	 * @since 1.0
	 */
	public Element getLastElement(){
		return childElements.lastElement();
	}

	/**
	 * 获得父元素
	 * @return 返回父元素,如果没有返回<tt>null<tt>
	 * @since 1.0
	 */
	public Element getParentElement() {
		return parentElement;
	}

	/**
	 * 设置当前元素的父元素
	 * @param parentElement 父元素
	 * @since 1.0
	 */
	public void setParentElement(Element parentElement) {
		this.parentElement = parentElement;
	}
	
	/**
	 * 给HTML元素添加一个属性
	 * @param key 属性名
	 * @param value 属性值
	 * @since 1.0
	 */
	public void addAttribute(String key, String value){
		attributes.put(key.toUpperCase(), value);
	}
	
	/**
	 * 返回HTML元素的一个属性值
	 * @param key 属性名
	 * @return 如果该属性名存在，返回其对应的属性值，否则返回<tt>null<tt>
	 * @since 1.0
	 */
	public String attribute(String key){
		return attributes.get(key.toUpperCase())==null ? "" : attributes.get(key.toUpperCase());
	}
	
	
	
	@Override
	public String toString() {
//		return LT + getName() + SPACE + attributesToString() + GT + 
//				getText() + childElementToString(new StringBuilder() , this).toString() +LT + FRASL + getName() + GT;
		
		return  getName();
	}
	
	/**
	 * 显示元素信息
	 * @since 1.0
	 */
	public void displayElement(){
		StringBuilder strBuid = elementToString(new StringBuilder() , this);
		System.out.println(strBuid.toString());
		
		try {
			FileOutputStream fout = null;
			FileChannel fc = null;
			fout = new FileOutputStream("d:/ht.html");
			fc = fout.getChannel();
			//下一步是创建一个缓冲区并在其中放入一些数据 - 在这里，数据将从一个名为 message 的数组中取出，这个数组包含字符串 "Some bytes" 的 ASCII 字节(本教程后面将会解释 buffer.flip() 和 buffer.put() 调用)。
			
			byte[] contents = strBuid.toString().getBytes();
			
			ByteBuffer buffer = ByteBuffer.wrap(contents);
			fc.write(buffer);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private String attributesToString(){
		StringBuilder strBuid = new StringBuilder();
		if(attributes != null && attributes.size() > 0){
			for(Map.Entry<String, String> attrEntry : attributes.entrySet()){
				String key = attrEntry.getKey();
				String value = attrEntry.getValue();
				
				strBuid.append(key + EQUAL_STR + QUOTATION_MARKS + value + QUOTATION_MARKS + SPACE);
			}
			return strBuid.substring(0, strBuid.length()-1);//去掉最后的空格
		}
		return "";
	}
	
	private StringBuilder elementToString(StringBuilder strBuid, Element currParentElement){
//		strBuid.append(LT + currParentElement.getName() + SPACE + 
//				currParentElement.attributesToString() + GT + currParentElement.getText() + ENTER);
		strBuid.append(LT + currParentElement.getName());
		String attrStr = currParentElement.attributesToString().toString();
		if(attrStr != null && attrStr.trim() != ""){ //属性不为空
			strBuid.append("" + SPACE +  attrStr);
		}
		//strBuid.append(GT + currParentElement.getText());
		String text = currParentElement.getText();//内容
		
		Vector<Element> currChildElements = currParentElement.getChildElements();
		if(currChildElements != null && currChildElements.size() > 0){// 有子元素
			strBuid.append("" + GT + ENTER);//加上右括号和回车
			for(Element childEle : currChildElements){
//				strBuid.append( LT + childEle.getName() + SPACE + childEle.attributesToString() + GT + 
//					childEle.getText() + ENTER);
				
				elementToString(strBuid, childEle);
			}
			
			strBuid.append(text + LT + "" + FRASL + currParentElement.getName() + GT + ENTER);
		}else{
			if(text != null && text.trim() != ""){
				strBuid.append(GT + text + LT + "" + FRASL + currParentElement.getName() + GT + ENTER);
			}else{
				strBuid.append("" + FRASL + GT + ENTER);
			}
		}
		
		
		
		return strBuid;
	}
	
}
